package com.orctom.mojo.was.utils;
import com.orctom.mojo.was.Constants;
import com.orctom.was.model.WebSphereModel;
import com.orctom.was.utils.CommandUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.taskdefs.Typedef;
import org.apache.tools.ant.types.Path;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
/**
* Utils to execute ant tasks
* Created by CH on 3/19/14.
*/
public class AntTaskUtils {
/**
* The refid used to store the Maven project object in the Ant build.
*/
private final static String DEFAULT_MAVEN_PROJECT_REFID = "maven.project";
/**
* The refid used to store the Maven project object in the Ant build.
*/
private final static String DEFAULT_MAVEN_PROJECT_HELPER_REFID = "maven.project.helper";
/**
* The path to The XML file containing the definition of the Maven tasks.
*/
private final static String ANTLIB = "org/apache/maven/ant/tasks/antlib.xml";
/**
* The default target name.
*/
private final static String DEFAULT_ANT_TARGET_NAME = "main";
public static void execute(WebSphereModel model, PlexusConfiguration target, MavenProject project,
MavenProjectHelper projectHelper, List<Artifact> pluginArtifact, Log logger)
throws IOException, MojoExecutionException {
// The fileName should probably use the plugin executionId instead of the targetName
boolean useDefaultTargetName = false;
String antTargetName = target.getAttribute("name");
if (null == antTargetName) {
antTargetName = DEFAULT_ANT_TARGET_NAME;
useDefaultTargetName = true;
}
StringBuilder fileName = new StringBuilder(50);
fileName.append("build");
if (StringUtils.isNotBlank(model.getHost())) {
fileName.append("-").append(model.getHost());
}
if (StringUtils.isNotBlank(model.getApplicationName())) {
fileName.append("-").append(model.getApplicationName());
}
fileName.append("-").append(antTargetName).append("-").append(CommandUtils.getTimestampString()).append(".xml");
File buildFile = getBuildFile(project, fileName.toString());
if (model.isVerbose()) {
logger.info("ant fileName: " + fileName);
}
if (buildFile.exists()) {
logger.info("[SKIPPED] already executed");
return;
}
StringWriter writer = new StringWriter();
AntXmlPlexusConfigurationWriter xmlWriter = new AntXmlPlexusConfigurationWriter();
xmlWriter.write(target, writer);
StringBuffer antXML = writer.getBuffer();
if (useDefaultTargetName) {
stringReplace(antXML, "<target", "<target name=\"" + antTargetName + "\"");
}
final String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
antXML.insert(0, xmlHeader);
final String projectOpen = "<project name=\"" + Constants.PLUGIN_ID + "\" default=\"" + antTargetName + "\">\n";
int index = antXML.indexOf("<target");
antXML.insert(index, projectOpen);
final String projectClose = "\n</project>";
antXML.append(projectClose);
buildFile.getParentFile().mkdirs();
FileUtils.fileWrite(buildFile.getAbsolutePath(), "UTF-8", antXML.toString());
Project antProject = generateAntProject(model, buildFile, project, projectHelper, pluginArtifact, logger);
antProject.executeTarget(antTargetName);
}
private static File getBuildFile(MavenProject project, String fileName) {
String path = project.getBuild().getDirectory() + File.separator + Constants.PLUGIN_ID + File.separator + "steps" + File.separator;
return new File(path, fileName);
}
private static Project generateAntProject(WebSphereModel model, File antBuildFile, MavenProject project, MavenProjectHelper projectHelper,
List<Artifact> pluginArtifact, Log logger)
throws MojoExecutionException {
try {
Project antProject = new Project();
ProjectHelper.configureProject(antProject, antBuildFile);
antProject.init();
setupLogger(antBuildFile, logger, antProject);
antProject.setBaseDir(project.getBasedir());
Path p = new Path(antProject);
p.setPath(StringUtils.join(project.getCompileClasspathElements().iterator(), File.pathSeparator));
antProject.addReference("maven.compile.classpath", p);
p = new Path(antProject);
p.setPath(StringUtils.join(project.getRuntimeClasspathElements().iterator(), File.pathSeparator));
antProject.addReference("maven.runtime.classpath", p);
p = new Path(antProject);
p.setPath(StringUtils.join(project.getTestClasspathElements().iterator(), File.pathSeparator));
antProject.addReference("maven.test.classpath", p);
antProject.addReference("maven.plugin.classpath", getPathFromArtifacts(pluginArtifact, antProject));
antProject.addReference(DEFAULT_MAVEN_PROJECT_REFID, project);
antProject.addReference(DEFAULT_MAVEN_PROJECT_HELPER_REFID, projectHelper);
initMavenTasks(antProject);
copyProperties(project, antProject);
copyProperties(model.getProperties(), antProject);
return antProject;
} catch (DependencyResolutionRequiredException e) {
throw new MojoExecutionException("DependencyResolutionRequiredException: " + e.getMessage(), e);
} catch (BuildException e) {
throw new MojoExecutionException("An Ant BuildException has occurred: " + e.getMessage(), e);
} catch (Throwable e) {
throw new MojoExecutionException("Error executing ant tasks: " + e.getMessage(), e);
}
}
private static void setupLogger(File antBuildFile, Log logger, Project antProject) throws FileNotFoundException {
DefaultLogger consoleLogger = new DefaultLogger();
consoleLogger.setOutputPrintStream(System.out);
consoleLogger.setErrorPrintStream(System.err);
addBuildListener(logger, antProject, consoleLogger);
DefaultLogger fileLogger = new DefaultLogger();
PrintStream ps = new PrintStream(new FileOutputStream(new File(antBuildFile.getAbsolutePath() + ".log")));
fileLogger.setOutputPrintStream(ps);
fileLogger.setErrorPrintStream(ps);
addBuildListener(logger, antProject, fileLogger);
}
private static void addBuildListener(Log logger, Project antProject, DefaultLogger listener) {
if (logger.isDebugEnabled()) {
listener.setMessageOutputLevel(Project.MSG_DEBUG);
} else if (logger.isInfoEnabled()) {
listener.setMessageOutputLevel(Project.MSG_INFO);
} else if (logger.isWarnEnabled()) {
listener.setMessageOutputLevel(Project.MSG_WARN);
} else if (logger.isErrorEnabled()) {
listener.setMessageOutputLevel(Project.MSG_ERR);
} else {
listener.setMessageOutputLevel(Project.MSG_VERBOSE);
}
antProject.addBuildListener(listener);
}
private static void stringReplace(StringBuffer text, String match, String with) {
int index = text.indexOf(match);
if (index != -1) {
text.replace(index, index + match.length(), with);
}
}
private static Path getPathFromArtifacts(Collection<Artifact> artifacts, Project antProject)
throws DependencyResolutionRequiredException {
if (artifacts == null) {
return new Path(antProject);
}
List<String> list = new ArrayList<String>(artifacts.size());
for (Artifact a : artifacts) {
File file = a.getFile();
if (file == null) {
throw new DependencyResolutionRequiredException(a);
}
list.add(file.getPath());
}
Path p = new Path(antProject);
p.setPath(StringUtils.join(list.iterator(), File.pathSeparator));
return p;
}
private static void initMavenTasks(Project antProject) {
Typedef typedef = new Typedef();
typedef.setProject(antProject);
typedef.setResource(ANTLIB);
typedef.execute();
}
private static void copyProperties(MavenProject mavenProject, Project antProject) {
copyProperties(mavenProject.getProperties(), antProject);
// Set the POM file as the ant.file for the tasks run directly in Maven.
antProject.setProperty("ant.file", mavenProject.getFile().getAbsolutePath());
// Add some of the common maven properties
antProject.setProperty(("project.groupId"), mavenProject.getGroupId());
antProject.setProperty(("project.artifactId"), mavenProject.getArtifactId());
antProject.setProperty(("project.name"), mavenProject.getName());
if (mavenProject.getDescription() != null) {
antProject.setProperty(("project.description"), mavenProject.getDescription());
}
antProject.setProperty(("project.version"), mavenProject.getVersion());
antProject.setProperty(("project.packaging"), mavenProject.getPackaging());
antProject.setProperty(("project.build.directory"), mavenProject.getBuild().getDirectory());
antProject.setProperty(("project.build.outputDirectory"), mavenProject.getBuild().getOutputDirectory());
antProject.setProperty(("project.build.testOutputDirectory"), mavenProject.getBuild().getTestOutputDirectory());
antProject.setProperty(("project.build.sourceDirectory"), mavenProject.getBuild().getSourceDirectory());
antProject.setProperty(("project.build.testSourceDirectory"), mavenProject.getBuild().getTestSourceDirectory());
}
private static void copyProperties(Properties properties, Project antProject) {
for (Object o : properties.keySet()) {
String key = (String) o;
antProject.setProperty(key, properties.getProperty(key));
}
}
}